﻿using DocumentFormat.OpenXml.Spreadsheet;
using FileManager.Util;
using Microsoft.VisualBasic;
using MyPinYin;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace FileManager.Model
{
    public class DW
    {
        public string Dwm { get; set; }
        public string Dwmch { get; set; }
        public string DwPy { get; set; }
        public string StarTime { get; set; }
        public string EndTime { get; set; }
        public string SignDate { get; set; }
    }
    public record Letter(string Name,String Path);


    public record LetterData
    {
        [XmlElement(ElementName = "Hash")]
        public required string Hash { get; init; }
        [XmlElement(ElementName = "Name")]
        public string Name { get; init; }
        [XmlElement(ElementName = "Path")]
        public required string Path { get; init; }

        [SetsRequiredMembers]
        public LetterData(string Name, string Path)
        {
            this.Name = Name;
            this.Path = Path;
            this.Hash = HashHelper.GetFileHash256(Path);
            string name = System.IO.Path.GetFileNameWithoutExtension(Name);
            string[] infos = name.Split('_');
            if (infos.Length > 1)
            {
                Dwmch = infos[2];
                DwPy = PinYinConverter.GetFirst(infos[2]);
                Hash = HashHelper.GetFileHash256(Path);
                StarTime = infos[0];
                EndTime = infos[1];
                SignDate = infos.Count() > 3 ? infos[3] : infos[0];
            }
        }
        public static LetterData FromMeta(MetaData meta) {

            // 防御性检查：确保输入不为空
            if (string.IsNullOrEmpty(meta.FileName))
                throw new ArgumentException("文件名不能为空", nameof(meta));
            // 使用 Path.GetFileNameWithoutExtension 自动处理：
            // 1. 移除扩展名（如 .docx）
            // 2. 忽略路径信息（即使不存在路径也不会报错）
            return new(meta.FileName, meta.Path);
        }

        public static explicit operator LetterData(Letter letter)
        {
            if (letter == null)
                throw new ArgumentNullException(nameof(letter), "无法转换");
            string[] infos = letter.Name.Split('_');
            if(infos.Length>1)
            {
                return new LetterData(letter.Name, letter.Path)
                {
                    Dwmch = infos[2],
                    DwPy = PinYinConverter.GetFirst(infos[2]),
                    Hash=HashHelper.GetFileHash256(letter.Path),
                    StarTime = infos[0],
                    EndTime = infos[1],
                    SignDate = infos.Count() > 3 ? infos[3] : infos[0]
                };
            }
            return new LetterData(letter.Name, letter.Path);
        }


        [XmlElement(ElementName = "Dwmch")]
        public string Dwmch { get; set; }
        [XmlElement(ElementName = "DwPy")]
        public string DwPy { get; set; }

        [XmlElement(ElementName = "StarTime")]
        public string StarTime { get; set; }

        [XmlElement(ElementName = "EndTime")]
        public string EndTime { get; set; }

        [XmlElement(ElementName = "SignDate")]
        public string SignDate { get; set; }

        [XmlElement(ElementName = "Bank")]
        public string Bank { get; set; }

        [XmlElement(ElementName = "Tag")]
        public List<string> Tag { get; set; } = new List<string>();
        public LetterData() { }
    }
    [XmlRoot("LetterDataCollection")]
    public class LetterDataCollection : ICollection<LetterData>
    {

        [XmlElement("LetterData")]
        private List<LetterData> Items { get; set; } = new List<LetterData>();

        #region ICollection<MetaData> Implementation

        public LetterData this[int index]
        {
            get => Items[index];
            set => Items[index] = value;
        }

        public int Count => Items.Count;

        public bool IsReadOnly => false;

        public void Add(LetterData item)
        {
            Items.Add(item);
        }

        public void Clear()
        {
            Items.Clear();
        }

        public bool Contains(LetterData item)
        {
            return Items.Contains(item);
        }

        public void CopyTo(LetterData[] array, int arrayIndex)
        {
            Items.CopyTo(array, arrayIndex);
        }
        public int IndexOf(LetterData metaData)
        {
            return Items.IndexOf(metaData);
        }
        public IEnumerator<LetterData> GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        public bool Remove(LetterData item)
        {
            return Items.Remove(item);
        }
        public LetterDataCollection Clone()
        {
            LetterData[] metas = new LetterData[Items.Count];
            Items.ToList().CopyTo(metas);
            return new LetterDataCollection() { Items = metas.ToList()};
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        public static LetterDataCollection FromEnumerable(IEnumerable<LetterData> source)
        {
            var collection = new LetterDataCollection();
            if (source != null)
            {
                foreach (var item in source)
                {
                    collection.Items.Add(item);
                }
            }
            return collection;
        }
        public static LetterDataCollection FromEnumerable(IEnumerable<Letter> source)
        {
            var collection = new LetterDataCollection();
            if (source != null)
            {
                foreach (var item in source)
                {
                    collection.Items.Add((LetterData)item);
                }
            }
            return collection;
        }

        public IEnumerable<Letter> ToCloneEnumerable()
        {
            List<Letter> letters = new List<Letter>();
            Items.ForEach(a => letters.Add(new Letter(a.Name, a.Path)));
            return letters;
        }
    }

    public static class LetterDataUtils
    {
        public static void SaveToFile(LetterDataCollection collection, string filePath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(LetterDataCollection));
            using (FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                serializer.Serialize(fileStream, collection);
            }
        }

        private static void Ini(string xmlFilePath)
        {
            if (!Path.Exists(xmlFilePath))
            {
                File.Create(xmlFilePath);
            }
        }
        public static LetterDataCollection LoadFromFile(string filePath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(LetterDataCollection));
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
            {
                return (LetterDataCollection)serializer.Deserialize(fileStream);
            }
        }

        public static LetterData? FindByPath(LetterDataCollection collection, string targetPath)
        {
            return collection.FirstOrDefault(item => item.Path == targetPath);
        }
        /// <summary>
        /// 根据名称搜索
        /// </summary>
        /// <param name="collection">委托书集合</param>
        /// <param name="searchName">单位名称</param>
        /// <returns></returns>
        public static IEnumerable<LetterData> FindByName(LetterDataCollection collection, string searchName)
        {
            // 过滤出Dwmch包含搜索名称的项并缓存结果
            var exactMatchResults = collection.Where(item => item.Dwmch.Contains(searchName)).ToList();

            // 检查是否存在任何精确匹配项
            if (exactMatchResults.Any())
            {
                return exactMatchResults;
            }

            // 使用WordCompare获取相似名称
            var similarNames = WordCompare.GetSimilar(searchName, 3);
            if(!similarNames.Any())
                similarNames=WordCompare.GetSimilar(searchName, 3,0.3d,true);
            // 将集合与相似名称进行连接，并返回匹配的LetterData项
            return collection.Join(similarNames,
                                  item => item.Dwmch,
                                  name => name,
                                  (item, name) => item);
        }
        public static List<LetterData> FindByTag(LetterDataCollection collection, string tag)
        {
            if (String.IsNullOrEmpty(tag))
                return collection.ToList();
            var tagArr = tag.Split(',', '，', '|', '、', '\\');
            return collection.Where(item =>tagArr.All(a=>item.Tag.Contains(a))).ToList();
        }
        public static List<LetterData> FindByHash(LetterDataCollection collection, string hash)
        {
            return collection.Where(item => item.Hash == hash).ToList();
        }
        public static void UpdateLetterData(string xmlFilePath, LetterData updatedMetadata)
        {
            // 1. 加载XML文件
            var serializer = new XmlSerializer(typeof(LetterDataCollection));
            LetterDataCollection collection = null;
            using (var fileStream = new FileStream(xmlFilePath, FileMode.Open, FileAccess.Read))
            {
                collection = (LetterDataCollection)serializer.Deserialize(fileStream);
                // 2. 查找并更新匹配的元数据
                var matchingItem = collection.FirstOrDefault(item => item.Hash == updatedMetadata.Hash);
                if (matchingItem != null)
                {
                    var index = collection.IndexOf(matchingItem);
                    collection[index] = updatedMetadata;
                }
            }
            if (null != collection)
            {
                // 3. 保存更新后的XML文件
                using (var outputStream = new FileStream(xmlFilePath, FileMode.Truncate, FileAccess.Write))
                {
                    serializer.Serialize(outputStream, collection);
                }
            }
        }
        public static void AddOrUpdateLetterData(string xmlFilePath, LetterData newMetadata)
        {
            // 1. 加载XML文件
            var serializer = new XmlSerializer(typeof(LetterDataCollection));
            LetterDataCollection collection = null;
            using (var fileStream = new FileStream(xmlFilePath, FileMode.Open, FileAccess.Read))
            {
                collection = (LetterDataCollection)serializer.Deserialize(fileStream);
                // 2. 查找并更新匹配的元数据
                var matchingItem = collection.FirstOrDefault(item => item.Hash == newMetadata.Hash);
                if (matchingItem != null)
                {
                    var index = collection.IndexOf(matchingItem);
                    collection[index] = newMetadata;
                }
                else
                {
                    collection.Add(newMetadata);
                }
            }
            if (null != collection)
            {
                // 3. 保存更新后的XML文件
                using (var outputStream = new FileStream(xmlFilePath, FileMode.Truncate, FileAccess.Write))
                {
                    serializer.Serialize(outputStream, collection);
                }
            }
        }


        public static void RemoveLetterData(string xmlFilePath, LetterData updatedMetadata)
        {
            // 1. 加载XML文件
            var serializer = new XmlSerializer(typeof(LetterDataCollection));
            LetterDataCollection collection = null;
            using (var fileStream = new FileStream(xmlFilePath, FileMode.Open, FileAccess.Read))
            {
                collection = (LetterDataCollection)serializer.Deserialize(fileStream);

                // 2. 查找并更新匹配的元数据
                var matchingItem = collection.Where(item => item.Hash == updatedMetadata.Hash).ToList();

                if (matchingItem != null)
                {
                    matchingItem.ForEach(a => collection.Remove(a));
                }
            }
            if (null != collection)
            {
                // 3. 保存更新后的XML文件
                using (var outputStream = new FileStream(xmlFilePath, FileMode.Truncate, FileAccess.Write))
                {
                    serializer.Serialize(outputStream, collection);
                }
            }
        }


    }
}
